// DMPluginWrapper.h

#pragma once

#include "dmalgointerfaces.h"
#include <oledbdm.h>

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::InteropServices;

#include "DMEnumerationWrappers.h"
#include "DMMiningParameter.h"
#include "DMCaseIterHelper.h"
#include "DMAttributeSet.h"
#include "DMCustomFunctions.h"

namespace Microsoft
{
namespace SqlServer
{
namespace DataMining
{
namespace PluginAlgorithms
{
    ref class PushCaseSet;
	ref class AlgorithmBase;
	ref class AlgorithmNavigationBase;
	ref class AttributeSet;    
	ref class MarginalStats; 
	ref class MiningParameterCollection;
	ref class MiningCase;
	ref class StateValue;
	ref class PersistenceReader;
	ref class PersistenceWriter;
	ref class PredictionResult;
	ref class ClusterMembershipInfo;
	ref class PMMLWriter;
    


    
	///////////////////////////////////////////////////////////
	// AlgorithmBase -- Implements IDMAlgorithm
	public  ref class AlgorithmBase abstract: 
                            public ICLR_DMAlgorithm,
							public ICLR_DMPersist,
							public ICLR_DMDispatch,
							public ICLR_DMClusteringAlgorithm,
							public ICLR_SupportErrorInfo
	{
    private:
        // Constants
        ContextServices ^				m_context;
		ModelServices	^				m_model;
		MarginalStats	^				m_marginalStats;
		AttributeSet	^				m_attrSet;

		array<CustomFunctionInfo^>^		m_rgCustomFunctionInfo;
		
	
	internal:
		void	SetModelServices( ModelServices ^	model )
		{
			m_model = model;
		}

		property array<CustomFunctionInfo^>^ CustomFunctions
		{
			void set(array<CustomFunctionInfo^>^ val)
			{
				m_rgCustomFunctionInfo = val;
			}
		}

		System::Xml::XmlWriter^		GetPMMLWriter()
		{
			return m_pmmlRecorder;
		}

		void	SavePMMLParsingState(int nDepth)
		{
			m_pmmlSwitchDepth	=	nDepth;
		}


		Object^		InternalInvokeFunction(
				CustomFunctionInfo^			in_funcInfo,
				DM_CaseID					in_CaseID,
				ULONG						in_ulCaseValues,
				DM_ATTRIBUTE_VALUE*			in_rgValues,
				ULONG						in_ulFlags,
				ULONG*						in_rgFlags,
				ULONG						in_ulParams,
				DMVariantPtr*				in_rgParams
				);


    protected:
            // Constructor
        AlgorithmBase();


        // Destructor
        ~AlgorithmBase();

	public:
		

		property ModelServices ^ Model
		{
			ModelServices ^ get()
			{
				return m_model;
			}
		}

		
		property PluginAlgorithms::AttributeSet^	AttributeSet
		{
			PluginAlgorithms::AttributeSet^	get()
			{
				return m_attrSet;
			}
		}

		

		property PluginAlgorithms::MarginalStats^	MarginalStats
		{
			PluginAlgorithms::MarginalStats^	get()
			{
				return m_marginalStats;
			}
		}

        // property accessible from inside the derived classes
        
		property ContextServices ^    Context
		{
			ContextServices ^    get()
			{
				return m_context;
			}
		}

		virtual HRESULT ExportedInitialize(
			IDMContextServices* in_pContext ,
			IDMAttributeSet*	in_pAttributeSet ,
			IDMMarginalStat*	in_pMarginalStat)sealed;

			
        
		virtual HRESULT ExportedInsertCases( 
            IDMContextServices *in_pExeContext,
            IDMPushCaseSet *in_pCaseSet,
            ULONG in_ulNumParameters,
            WCHAR*  in_rgParameterNames [],
            DMVariantPtr  in_rgParameterValues [])sealed;

		virtual HRESULT ExportedPredict( 
            IDMContextServices *in_pContext,
            DM_PREDICTION_FLAGS in_Flags,
            IDMAttributeGroup *in_pPredAttGroup,
            DM_CaseID in_CaseID,
            ULONG in_ulCaseValues,
            DM_ATTRIBUTE_VALUE *in_rgValues,
            ULONG in_ulMaxPredictions,
            ULONG in_ulMaxStates,
            DM_ATTRIBUTE_STAT **io_prgPredictions,
            ULONG *out_pulPredictions)sealed;
        
		virtual HRESULT ExportedGetNodeIDsForCase( 
            IDMContextServices *in_pContext,
            DM_NODE_FLAGS in_Flags,
            DM_CaseID in_CaseID,
            ULONG in_ulCaseValues,
            DM_ATTRIBUTE_VALUE *in_rgValues,
            ULONG in_ulMaxNodeIDs,
            DMStringPtr **io_prgNodeIDs,
            ULONG *out_pulNodeIDs)sealed;
        
		virtual HRESULT ExportedGetNavigator( 
            IDMContextServices *in_pContext,
            BOOL in_fForDMDimensionContent,
            IDMAlgorithmNavigation **out_ppDAGNav)sealed;
        
		virtual HRESULT ExportedGetSampleCaseSet( 
            IDMContextServices *in_pContext,
            DMString *in_pstrNodeID,
            IDMPullCaseSet **out_ppCaseSet)sealed;
        
		virtual HRESULT ExportedGetTrainingParameterActualValue( 
            IDMContextServices *in_pContext,
            ULONG in_iParameter,
            DMVariantPtr io_pParameterValue)sealed;
        
		virtual HRESULT ExportedHasFeatureSelection( 
            IDMContextServices *in_pContext,
            BOOL *out_pHasFS)sealed;
        
		virtual HRESULT ExportedGetFeatureSelectedAttributes( 
            IDMContextServices *in_pContext,
            ULONG *out_pCount,
            DM_Attribute **out_prgFeatureSelectedAttributes,
            DM_ATTRIBUTE_FLAGS **out_prgFSAttributeFlags)sealed;
        
		virtual HRESULT ExportedGetAttributeFeatureSelectionFlags( 
            IDMContextServices *in_pContext,
            DM_Attribute in_nAttr,
            DM_ATTRIBUTE_FLAGS *out_pAttFlags)sealed;
        
		virtual HRESULT ExportedGetProcessingMemoryEstimate( 
            IDMContextServices *in_pContext,
            LONG *out_pEstimate)sealed;
        
		virtual void ExportedUpdateMemoryEstimate( 
            LONG in_lEstimateChange)sealed;
        
		virtual LONG ExportedReservedMemoryEstimate( void)sealed;
        
		virtual HRESULT ExportedRenderPMMLContent( 
            IDMContextServices *in_pContext,
            ISAXContentHandler *in_pXMLWriter)sealed;
        
		virtual HRESULT ExportedPreInitializeForPMML21Parsing( 
            IDMContextServices *in_pContext,
            IDMAttributeSet *in_pAttributeSet)sealed;

		virtual HRESULT ExportedGetPMMLAlgorithmSAXHandler( 
            IDMContextServices *in_pContext,
            ISAXContentHandler **out_ppSAXHandler)sealed;

		
		// IDMPersist interface
		virtual HRESULT ExportedLoad(
			IDMContextServices* in_pContext,
			IDMPersistenceReader* in_pReader)sealed;

		
		virtual HRESULT ExportedSave(
			IDMContextServices* in_pContext,
			IDMPersistenceWriter* in_pWriter)sealed;

		//IDMDispatch interface
		virtual HRESULT ExportedPrepareFunction(
				IDMContextServices*			in_pContext,
				DM_SUPPORTED_FUNCTION		in_Function,
				ULONG						in_ulFlags,
				ULONG*						in_rgFlags,
				ULONG						in_ulParams,
				DMVariantPtr*				in_rgParams,
				DM_COLUMN_INFO**			out_prgColumnInfo,
				ULONG*						out_pulColumnInfo)sealed;

		virtual HRESULT ExportedInvokeFunction(
				IDMContextServices*			in_pContext,
				DM_SUPPORTED_FUNCTION		in_Function,
				DM_CaseID					in_CaseID,
				ULONG						in_ulCaseValues,
				DM_ATTRIBUTE_VALUE*			in_rgValues,
				ULONG						in_ulFlags,
				ULONG*						in_rgFlags,
				ULONG						in_ulParams,
				DMVariantPtr*				in_rgParams,
				DMVariantPtr				io_pResult)sealed;



		//ISupportErrorInfo interface
		virtual HRESULT ExportedInterfaceSupportsErrorInfo(
				REFIID			riid)sealed;

		// IDMClusteringAlgorithm
		virtual HRESULT ExportedClusterMembership(
			IDMContextServices*			in_pContext,
			DM_CLUSTER_MEMBERSHIP_FLAGS	in_Flags,
			DMStringPtr					in_strClusterCaption,
			DM_CaseID						in_CaseID,
			ULONG							in_ulCaseValues,
			DM_ATTRIBUTE_VALUE *			in_rgValues,
			ULONG							in_ulMaxClusters,
			DM_CLUSTER_MEMBERSHIP **		io_prgClusters,
			ULONG *						out_pulClusters)sealed;


		virtual HRESULT ExportedCaseLikelihood(
			IDMContextServices*			in_pContext,
			DM_CASE_LIKELIHOOD_FLAGS		in_Flags,
			DM_CaseID						in_CaseID,
			ULONG							in_ulCaseValues,
			DM_ATTRIBUTE_VALUE *			in_rgValues,
			DOUBLE *						out_pdblCaseLikelihood)sealed;


        private:
            //
            //    Pinned arrays of enumerated values. 
            //    These are members to keep them in scope after returning from 
            //    GetSup functions
            //
        protected:
			virtual void Initialize(){};
			
			virtual void				InsertCases(PushCaseSet ^ caseSet, MiningParameterCollection ^ trainingParameters) = 0;
			virtual void				Predict( MiningCase ^	inputCase, PredictionResult ^	predictionResult) = 0;
			virtual AlgorithmNavigationBase ^ GetNavigator(System::Boolean forDMDimensionContent) = 0;
			virtual Object ^			GetTrainingParameterActualValue( System::Int32 parameterOrdinal ) {return nullptr;}
			virtual array<String^>^		GetNodeIDsForCase(DrillThroughNodeFlags	nodeFlags, 	
														  System::Int64 caseId, 
														  MiningCase ^ inputCase,
														  System::UInt64 maxNodes){return nullptr;} 

			// Persistence methods
			virtual void SaveContent(PersistenceWriter^ writer ) = 0;
			virtual void LoadContent(PersistenceReader^ reader ) = 0;


			// PMML Methods
			[System::Diagnostics::CodeAnalysis::SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased")]
			virtual void	RenderPMMLContent(PMMLWriter^ pmmlWriter)
			{
				throw gcnew System::NotSupportedException();
			}

			[System::Diagnostics::CodeAnalysis::SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased")]
			[System::Diagnostics::CodeAnalysis::SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
			virtual void	LoadPMMLContent( System::Xml::XmlElement^ algorithmContent)
			{
				throw gcnew System::NotSupportedException();
			}

			// IDMClustering implementation methods
			virtual array<ClusterMembershipInfo^>^	ClusterMembership( 
													System::Int64	caseId, 
													MiningCase^		inputCase, 
													String^			targetCluster)
			{
				throw gcnew System::NotSupportedException();
			}


			virtual System::Double CaseLikelihood( 
													System::Int64	caseId, 
													MiningCase^		inputCase, 
													bool			normalized)
			{
				throw gcnew System::NotSupportedException();
			}

			// Geature selection methods
			virtual bool	HasFeatureSelection() { return false;}

			virtual void	GetAllFeatureSelectionInfo(
								[Out] array<System::UInt32>^%	attributes, 
								[Out] array<AttributeFlags>^%	selectionFlags)
			{
				// By default, populate the array with all the attributes and mark them all 
				// as feature-selected for both input and output
				int	cArrCount	=	(int)AttributeSet->GetAttributeCount();
				attributes     = gcnew array<System::UInt32>(cArrCount);
				selectionFlags = gcnew array<AttributeFlags>(cArrCount);
				for( int nIndex = 0; nIndex < cArrCount; nIndex ++ )
				{
					attributes[nIndex] = (unsigned int)nIndex;
					selectionFlags[nIndex]= AttributeFlags::Input | AttributeFlags::Output;
				}
				return;
			}

			virtual AttributeFlags	GetAttributeFeatureSelectionInfo( System::UInt32 attribute )
			{
				return AttributeFlags::Input | AttributeFlags::Output;
			}
        private:
			System::Xml::XmlWriter^			m_pmmlRecorder;
			System::IO::MemoryStream^		m_pmmlStream;
			int								m_pmmlSwitchDepth;



	};





}
}	
}							
}	
